package com.gexiaobao.pigeon.ui.activity

import android.content.Context
import android.content.Intent
import android.graphics.BitmapFactory
import android.os.Build
import android.os.Bundle
import android.text.Editable
import android.text.TextUtils
import android.text.TextWatcher
import android.view.animation.LinearInterpolator
import android.widget.AdapterView
import androidx.core.view.isVisible
import com.amap.api.location.AMapLocation
import com.amap.api.location.AMapLocationClient
import com.amap.api.location.AMapLocationClientOption
import com.amap.api.location.AMapLocationListener
import com.amap.api.maps.AMap
import com.amap.api.maps.AMap.OnCameraChangeListener
import com.amap.api.maps.AMapOptions
import com.amap.api.maps.CameraUpdateFactory
import com.amap.api.maps.MapsInitializer
import com.amap.api.maps.UiSettings
import com.amap.api.maps.model.BitmapDescriptorFactory
import com.amap.api.maps.model.CameraPosition
import com.amap.api.maps.model.LatLng
import com.amap.api.maps.model.Marker
import com.amap.api.maps.model.MarkerOptions
import com.amap.api.maps.model.MyLocationStyle
import com.amap.api.maps.model.animation.TranslateAnimation
import com.amap.api.services.core.AMapException
import com.amap.api.services.core.LatLonPoint
import com.amap.api.services.core.PoiItem
import com.amap.api.services.geocoder.GeocodeAddress
import com.amap.api.services.geocoder.GeocodeResult
import com.amap.api.services.geocoder.GeocodeSearch
import com.amap.api.services.geocoder.RegeocodeQuery
import com.amap.api.services.geocoder.RegeocodeResult
import com.amap.api.services.help.Inputtips
import com.amap.api.services.help.InputtipsQuery
import com.amap.api.services.help.Tip
import com.gexiaobao.pigeon.R
import com.gexiaobao.pigeon.app.base.BaseActivity
import com.gexiaobao.pigeon.app.model.bean.MapLocationBean
import com.gexiaobao.pigeon.app.util.KvUtils
import com.gexiaobao.pigeon.app.util.RxToast.showToast
import com.gexiaobao.pigeon.app.util.StatusBarUtil
import com.gexiaobao.pigeon.databinding.ActivityMapLocationBinding
import com.gexiaobao.pigeon.ui.adapter.PoiAdapter
import com.gexiaobao.pigeon.ui.dialog.RxDialogDefault
import com.gexiaobao.pigeon.viewmodel.MainViewModel
import com.hjq.permissions.OnPermissionCallback
import com.hjq.permissions.Permission
import com.hjq.permissions.XXPermissions
import me.hgj.jetpackmvvm.ext.util.setOnclickNoRepeat
import me.hgj.jetpackmvvm.util.finish


/**
 * @Author      : hxw
 * @Date        : 2024/6/19 8:58
 * @Describe    : 地图定位选址
 */
class ActivityMapLocation : BaseActivity<MainViewModel, ActivityMapLocationBinding>(), AMapLocationListener, GeocodeSearch.OnGeocodeSearchListener {

    private var aMap: AMap? = null
    private var mLocationClient: AMapLocationClient? = null
    private var poiAdapter: PoiAdapter? = null
    private val mapLocationBeanList: ArrayList<MapLocationBean> = arrayListOf()
    private var marker: Marker? = null
    private var city: String? = null
    private var selectMapLocationBean: MapLocationBean? = null
    private var geocoderSearch: GeocodeSearch? = null
    private var flag = false //条目点击标志位
    private var mProvinceCityArea = ""


    override fun initView(savedInstanceState: Bundle?) {
        StatusBarUtil.setTranslucentForImageView(this, 0, null)
        mDatabind.includeBar.tvTitle.text = getString(R.string.relocatable_address)
        mDatabind.includeSearch.tvSearch.isVisible = false
        //隐私合规接口
        MapsInitializer.updatePrivacyShow(this, true, true)
        MapsInitializer.updatePrivacyAgree(this, true)
        mDatabind.map.onCreate(savedInstanceState)
        positioning()
        if (!hasRequestedPermissions()) {
            showExplanationDialog()
        } else {
            initLocation()
            startLocation()
        }

        poiAdapter = PoiAdapter(mapLocationBeanList, this)
        mDatabind.listview.adapter = poiAdapter
        mDatabind.listview.onItemClickListener = AdapterView.OnItemClickListener { parent, view, position, id ->
            poiAdapter?.setSelectPosition(position)
            poiAdapter?.notifyDataSetChanged()
            selectMapLocationBean = mapLocationBeanList[position]
            flag = true //当是点击地址条目触发的地图移动时，不进行逆地理解析
            aMap?.animateCamera(CameraUpdateFactory.newLatLng(LatLng(selectMapLocationBean!!.latitude, selectMapLocationBean!!.longitude))) //设置地图中心点
            val intent = Intent()
            intent.putExtra("name", selectMapLocationBean?.name)
            intent.putExtra("address", selectMapLocationBean?.address)
            intent.putExtra("latitude", selectMapLocationBean?.latitude)
            intent.putExtra("longitude", selectMapLocationBean?.longitude)
            intent.putExtra("proCityArea", mProvinceCityArea)
            finish(intent)
        }

        //搜索监听
        mDatabind.includeSearch.editQuery.addTextChangedListener(object : TextWatcher {
            override fun beforeTextChanged(s: CharSequence, start: Int, count: Int, after: Int) {}
            override fun onTextChanged(s: CharSequence, start: Int, before: Int, count: Int) {
                if (!TextUtils.isEmpty(s.toString())) {
                    showTip(s.toString())
                }
            }

            override fun afterTextChanged(s: Editable) {}
        })

    }

    override fun onBindViewClick() {
        super.onBindViewClick()
        setOnclickNoRepeat(mDatabind.includeBar.ivBack) {
            when (it) {
                mDatabind.includeBar.ivBack -> {
                    finish()
                }
            }
        }
    }

    private fun positioning() {
        aMap = mDatabind.map.map
        //地图移动监听
        aMap?.setOnCameraChangeListener(object : OnCameraChangeListener {
            override fun onCameraChange(cameraPosition: CameraPosition) {}
            override fun onCameraChangeFinish(cameraPosition: CameraPosition) {
                if (!flag) {
                    if (poiAdapter != null) {
                        poiAdapter?.setSelectPosition(0)
                    }
                    try {
                        getGeocodeSearch(cameraPosition.target)
                        setMapCenter(cameraPosition.target)
                    } catch (e: AMapException) {
                        throw RuntimeException(e)
                    }
                    mDatabind.listview.smoothScrollToPosition(0)
                }
                flag = false
            }
        })
    }

    /**
     * 搜索tip
     */
    private fun showTip(input: String) {
        val inputQuery = InputtipsQuery(input, city)
        val inputTips = Inputtips(this, inputQuery)
        inputTips.setInputtipsListener { tipList: List<Tip>, rCode: Int ->
            if (rCode == AMapException.CODE_AMAP_SUCCESS) { // 正确返回
                if (tipList.isNotEmpty()) {
                    mapLocationBeanList.clear()
                    for (tip in tipList) {
                        if (tip.point != null) {
                            mapLocationBeanList.add(MapLocationBean(tip.name, tip.address, tip.point.latitude, tip.point.longitude))
                        }
                    }
                    poiAdapter!!.notifyDataSetChanged()
                    aMap!!.animateCamera(
                        CameraUpdateFactory.newLatLng(
                            LatLng(
                                tipList[0].point.latitude,
                                tipList[0].point.longitude
                            )
                        )
                    ) //设置地图中心点
                }
            } else {
                showToast(rCode.toString())
            }
        }
        inputTips.requestInputtipsAsyn()
    }

    private fun hasRequestedPermissions(): Boolean {
        return KvUtils.decodeBoolean("PermissionsRequested")
    }

    private fun showExplanationDialog() {
        val dialog = RxDialogDefault(this)
        dialog.setTitle("权限请求")
        dialog.setContent("我们需要访问您的位置以确保司机可以准确的找到您要交鸽的位置")
        dialog.setSureListener {
            dialog.dismiss()
            permission()
        }
        dialog.setCancelListener {
            finish()
        }
        dialog.setCanceledOnTouchOutside(false)
        dialog.setFullScreenWidth()
        dialog.show()
    }

    /**
     * 权限请求
     */
    private fun permission() {
        val permission: Array<String> = if (Build.VERSION.SDK_INT >= Build.VERSION_CODES.R) {
            arrayOf(
                Permission.ACCESS_COARSE_LOCATION,
                Permission.ACCESS_FINE_LOCATION,
                Permission.MANAGE_EXTERNAL_STORAGE,
            )
        } else {
            arrayOf(
                Permission.ACCESS_COARSE_LOCATION,
                Permission.ACCESS_FINE_LOCATION,
            )
        }
        XXPermissions.with(this)
            .permission(*permission).request(object : OnPermissionCallback {
                override fun onGranted(permissions: List<String>, allGranted: Boolean) {
                    if (allGranted) {
                        KvUtils.encode("PermissionsRequested", true)
                        initLocation()
                        startLocation()
                    } else {
                        showToast(getString(R.string.failure_to_grant))
                    }
                }

                override fun onDenied(permissions: List<String>, doNotAskAgain: Boolean) {
                    if (doNotAskAgain) {
                        XXPermissions.startPermissionActivity(this@ActivityMapLocation, permissions)
                    } else {
                        showToast(getString(R.string.permission_acquisition_failure))
                    }
                }
            })
    }

    /**
     * 初始化定位
     */
    private fun initLocation() {
        if (aMap == null) {
            aMap = mDatabind.map.map
        }
        //设置定位蓝点
        val myLocationStyle = MyLocationStyle()
        myLocationStyle.myLocationType(MyLocationStyle.LOCATION_TYPE_LOCATE) //定位一次，且将视角移动到地图中心点。
        aMap!!.myLocationStyle = myLocationStyle //设置定位蓝点的Style
        //设置缩放级别
        aMap!!.moveCamera(CameraUpdateFactory.zoomTo(15f))
        // 控件交互 缩放按钮、指南针、定位按钮、比例尺等
        val mUiSettings: UiSettings = aMap!!.uiSettings //定义一个UiSettings对象 //实例化UiSettings类对象
        mUiSettings.isZoomControlsEnabled = false
        mUiSettings.isMyLocationButtonEnabled = true //显示默认的定位按钮
        aMap!!.isMyLocationEnabled = true // 可触发定位并显示当前位置
        mUiSettings.isScaleControlsEnabled = true //控制比例尺控件是否显示
        mUiSettings.logoPosition = AMapOptions.LOGO_MARGIN_LEFT //设置logo位置
    }

    /**
     * 开始定位
     */
    private fun startLocation() {
        showLoading(getString(R.string.locating_center_punch))
        try {
            //获取位置信息
            mLocationClient = AMapLocationClient(this)
        } catch (e: Exception) {
            e.printStackTrace()
        }
        //初始化定位参数
        val mLocationOption = AMapLocationClientOption()
        //设置定位监听
        mLocationClient!!.setLocationListener(this)
        //设置定位模式为高精度模式，Battery_Saving为低功耗模式，Device_Sensors是仅设备模式
        mLocationOption.setLocationMode(AMapLocationClientOption.AMapLocationMode.Hight_Accuracy)
        //获取一次定位结果
        mLocationOption.setOnceLocation(true)
        //获取最近3s内精度最高的一次定位结果
        mLocationOption.setOnceLocationLatest(true)
        //设置定位参数
        mLocationClient!!.setLocationOption(mLocationOption)
        //启动定位
        mLocationClient!!.startLocation()
    }

    /**
     * 定位回调
     */
    override fun onLocationChanged(aMapLocation: AMapLocation?) {
        if (aMapLocation != null && aMapLocation.errorCode == AMapLocation.LOCATION_SUCCESS) {
            val latLng = LatLng(aMapLocation.latitude, aMapLocation.longitude)
            setMapCenter(latLng)
            city = aMapLocation.city
            aMap!!.animateCamera(CameraUpdateFactory.newLatLng(latLng)) //设置地图中心点
            mLocationClient!!.stopLocation()
            mLocationClient!!.onDestroy()
        }
    }

    /**
     * 设置中心点
     */
    private fun setMapCenter(latLng: LatLng) {
        val markerOptions = MarkerOptions()
            .icon(
                BitmapDescriptorFactory.fromBitmap(
                    BitmapFactory
                        .decodeResource(resources, R.mipmap.icon_map_location_address)
                )
            )
            .position(latLng)
        if (marker != null) {
            marker?.remove()
        }
        marker = aMap!!.addMarker(markerOptions)
        //坐标系转换，坐标信息转换为屏幕的中心点信息
        val markerPoint = aMap!!.projection.toScreenLocation(latLng)
        marker?.setFixingPointEnable(true)
        marker?.setPositionByPixels(markerPoint.x, markerPoint.y)
        //marker动画
        val point = aMap!!.projection.toScreenLocation(latLng)
        point.y -= dip2px(this)
        val target = aMap!!.projection.fromScreenLocation(point)
        //使用TranslateAnimation,填写一个需要移动的目标点
        val animation = TranslateAnimation(target)
        animation.setInterpolator(LinearInterpolator())
        val duration: Long = 300
        animation.setDuration(duration)
        animation.setInterpolator(LinearInterpolator())
        marker?.setAnimation(animation)
        marker?.startAnimation()
    }

    /**
     * dip和px转换
     */
    private fun dip2px(context: Context): Int {
        val scale = context.resources.displayMetrics.density
        return (30f * scale + 0.5f).toInt()
    }

    /**
     * 逆地理编码获取当前位置信息
     */
    @Throws(AMapException::class)
    private fun getGeocodeSearch(target: LatLng) {
        if (geocoderSearch == null) {
            geocoderSearch = GeocodeSearch(this)
            geocoderSearch?.setOnGeocodeSearchListener(this)
        }
        // 第一个参数表示一个Latlng，第二参数表示范围多少米，第三个参数表示是火系坐标系还是GPS原生坐标系
        val query = RegeocodeQuery(LatLonPoint(target.latitude, target.longitude), 500f, GeocodeSearch.AMAP)
        query.extensions = "all"
        geocoderSearch?.getFromLocationAsyn(query)
    }

    override fun onRegeocodeSearched(regeocodeResult: RegeocodeResult, i: Int) {
        if (i != 1000) return
        mProvinceCityArea =
            regeocodeResult.regeocodeAddress.province + regeocodeResult.regeocodeAddress.city + regeocodeResult.regeocodeAddress.district
        mapLocationBeanList.clear()
        val poiItems: List<PoiItem> = regeocodeResult.regeocodeAddress.pois
        mapLocationBeanList.add(
            MapLocationBean(
                getString(R.string.current_position),
                regeocodeResult.regeocodeAddress.formatAddress,
                regeocodeResult.regeocodeQuery.point.latitude,
                regeocodeResult.regeocodeQuery.point.longitude
            )
        )
        if (poiItems.isNotEmpty()) {
            for (poiItem in poiItems) {
                mapLocationBeanList.add(
                    MapLocationBean(
                        poiItem.title,
                        poiItem.snippet,
                        poiItem.latLonPoint.latitude,
                        poiItem.latLonPoint.longitude
                    )
                )
            }
            poiAdapter!!.notifyDataSetChanged()
            dismissLoading()
        }
    }

    override fun onGeocodeSearched(geocodeResult: GeocodeResult?, p1: Int) {
        if (geocodeResult != null) {
            val geocodeAddressList: List<GeocodeAddress> = geocodeResult.geocodeAddressList
            if (geocodeAddressList.isNotEmpty()) {
                val address = geocodeAddressList[0]
            }
        }
    }

    override fun onDestroy() {
        super.onDestroy()
        //在activity执行onDestroy时执行mMapView.onDestroy()，销毁地图
        mDatabind.map.onDestroy()
        if (mLocationClient != null) {
            mLocationClient!!.onDestroy()
            mLocationClient = null
        }
        if (geocoderSearch != null) {
            geocoderSearch = null
        }
    }

    override fun onResume() {
        super.onResume()
        //在activity执行onResume时执行mMapView.onResume ()，重新绘制加载地图
        mDatabind.map.onResume()
    }

    override fun onPause() {
        super.onPause()
        //在activity执行onPause时执行mMapView.onPause ()，暂停地图的绘制
        mDatabind.map.onPause()
    }
}